package com.twj.tools.poi;

import com.sun.star.bridge.UnoUrlResolver;
import com.sun.star.bridge.XUnoUrlResolver;
import com.sun.star.comp.helper.Bootstrap;
import com.sun.star.uno.XComponentContext;
import org.jodconverter.core.DocumentConverter;
import org.jodconverter.local.LocalConverter;
import org.jodconverter.local.office.LocalOfficeManager;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 作者: tianwenju
 * @version 1.0
 * @project 金税三期工程核心征管及应用总集成项目
 * @package com.twj.tools.poi
 * @file T3.java 创建时间:2025年08月06日 9:51
 * @title 标题（要求能简洁地表达出类的功能和职责）
 * @description 描述（简要描述类的职责、实现方式、使用注意事项等）
 * @copyright Copyright (c) 2020 中国软件与技术服务股份有限公司
 * @company 中国软件与技术服务股份有限公司
 * @module 模块: 模块名称
 * @reviewer 审核人:
 * @history 修订历史（历次修订内容、修订人、修订时间等）
 */
public class T3 {

    public static void convertDoc2Pdf(String docFilePath, String pdfFilePath) throws Exception {

        String libreOfficePath = "C:\\Program Files\\LibreOffice";
//                 libreOfficePath = "C:\\Program Files (x86)\\OpenOffice 4";
        LocalOfficeManager officeManager = LocalOfficeManager.builder()
//                .officeHome(new File(libreOfficePath))
                .taskExecutionTimeout(180000L)
                .taskQueueTimeout(120000L)
                .disableOpengl(true)
//                .install()  // 自动查找Office安装路径
                .build();

        try {
            officeManager.start();

            // 设置加载属性 - 修复图片引用问题
            Map<String, Object> loadProperties = new HashMap<>();
            loadProperties.put("UpdateDocMode", 1);
            loadProperties.put("ReadOnly", true);
//            loadProperties.put("GraphicResolution", 300); // 提高图片分辨率
            loadProperties.put("LoadGraphic", true); // 强制加载图片
//            loadProperties.put("EmbedPictures", true); // 嵌入图片
//            loadProperties.put("Hidden", true);

            loadProperties.put("UpdateFields", true); // 更新所有字段
            loadProperties.put("UpdateLinks", true);  // 更新链接
            loadProperties.put("Hidden", true);

            // 添加字体配置
            loadProperties.put("DefaultFontName", "SimSun"); // 宋体
            loadProperties.put("DefaultFontEncoding", "134"); // GB2312 编码
            // 针对 .doc 文件的特殊处理
            if (docFilePath.toLowerCase().endsWith(".doc")) {
                // .doc 文件需要额外的属性来正确处理修订
                loadProperties.put("GraphicResolution", 300);
                loadProperties.put("EmbedPictures", true);
                // 强制接受修订的模式
                loadProperties.put("LoadDocumentMode", 1); // 1 = 自动接受修订
            }
            // 设置PDF导出属性 - 优化图片处理
            Map<String, Object> filterData = new HashMap<>();
            // 核心属性：确保不导出或显示修订
            filterData.put("ExportTrackedChanges", false);
            filterData.put("ShowTrackedChanges", false);
            filterData.put("PrintChanges", false);
            filterData.put("PrintAnnotations", false);
            filterData.put("UseRedlineColors", false);

            filterData.put("ExportBookmarksToPDFDestination", false);//true
            filterData.put("ExportFormFields", false);//true
            filterData.put("EmbedStandardFonts", false);
            filterData.put("ExportBookmarks", false);//
            filterData.put("OpenBookmarkLevels", -1);
            filterData.put("ImagePDF", true); // 确保图片正确导出
            filterData.put("ImageResolution", 150); // 设置图像DPI
//            filterData.put("ReduceImageResolution", false);

//            filterData.put("ConvertOOoTargetToPDFTarget", true); // 解决目标链接问题

            filterData.put("PrintChanges", false);
            filterData.put("PrintAnnotations", false);
            filterData.put("UseRedlineColors", false);


            filterData.put("ExportNotes", false);
            filterData.put("ExportHiddenText", false);
            filterData.put("ExportPlaceholderFields", false);

            Map<String, Object> storeProperties = new HashMap<>();
            storeProperties.put("FilterData", filterData);
            storeProperties.put("FilterName", "writer_pdf_Export");
            storeProperties.put("Overwrite", true);
            // 3. 创建转换器并应用属性
            DocumentConverter converter = LocalConverter.builder()
                    .officeManager(officeManager)
                    .loadProperties(loadProperties)  // 设置加载属性
                    .storeProperties(storeProperties) // 设置导出属性
                    .build();

//            if ("11".equals("11")) {
//                throw new Exception("word转pdf终止。。。。。。。。。。");
//            }
            // 4. 执行转换
            converter.convert(new File(docFilePath))
                    .to(new File(pdfFilePath))
                    .execute();




        } catch ( Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage()+"word转pdf失败 ,尝试命令行转换...");
            officeManager.stop();
            convertDocWithCommandLine(docFilePath, pdfFilePath);
        } finally {
            officeManager.stop();
        }
    }
    public static void convertDocCleanRevision(String docFilePath, String pdfFilePath) throws Exception {
        LocalOfficeManager officeManager = LocalOfficeManager.builder()
                .taskExecutionTimeout(180000L)
                .taskQueueTimeout(120000L)
                .disableOpengl(true)
                .build();

        try {
            officeManager.start();

            // 特殊的加载属性来处理修订
            Map<String, Object> loadProperties = new HashMap<>();
            // 关键属性：强制接受所有修订
            loadProperties.put("UpdateDocMode", 1); // ACCEPT_ALL
            loadProperties.put("LoadDocumentMode", 1); // LOAD_DOCUMENT_MODE_AUTOMATIC
            loadProperties.put("ReadOnly", true);
            loadProperties.put("Hidden", true);
            loadProperties.put("UpdateFields", true);
            loadProperties.put("UpdateLinks", true);

            // 图片相关属性
            loadProperties.put("GraphicResolution", 300);
            loadProperties.put("LoadGraphic", true);
            loadProperties.put("EmbedPictures", true);

            // 额外的修订处理属性
            loadProperties.put("ShowChanges", false);
            loadProperties.put("ShowInlineChanges", false);
            loadProperties.put("ShowChangesInMargin", false);
            loadProperties.put("ShowAnnotations", false);

            // PDF导出属性 - 最大程度隐藏修订
            Map<String, Object> filterData = new HashMap<>();
            filterData.put("ExportTrackedChanges", false);
            filterData.put("ShowTrackedChanges", false);
            filterData.put("PrintChanges", false);
            filterData.put("PrintAnnotations", false);
            filterData.put("UseRedlineColors", false);
            filterData.put("ExportBookmarks", false);
            filterData.put("ExportBookmarksToPDFDestination", false);
            filterData.put("ExportFormFields", false);
            filterData.put("EmbedStandardFonts", false);
            filterData.put("OpenBookmarkLevels", -1);
            filterData.put("ImagePDF", true);
            filterData.put("ImageResolution", 300);
            filterData.put("ReduceImageResolution", false);
            filterData.put("SelectPdfVersion", 1);
            filterData.put("ExportNotes", false);
            filterData.put("ExportHiddenText", false);
            filterData.put("ExportPlaceholderFields", false);
            filterData.put("UseTaggedPDF", true);

            Map<String, Object> storeProperties = new HashMap<>();
            storeProperties.put("FilterData", filterData);
            storeProperties.put("FilterName", "writer_pdf_Export");
            storeProperties.put("Overwrite", true);

            DocumentConverter converter = LocalConverter.builder()
                    .officeManager(officeManager)
                    .loadProperties(loadProperties)
                    .storeProperties(storeProperties)
                    .build();

            converter.convert(new File(docFilePath))
                    .to(new File(pdfFilePath))
                    .execute();

        } finally {
            officeManager.stop();
        }
    }


    public static void convertDocWithTwoStep2(String docFilePath, String pdfFilePath) throws Exception {
        LocalOfficeManager officeManager = LocalOfficeManager.builder()
                .taskExecutionTimeout(180000L)
                .taskQueueTimeout(120000L)
                .disableOpengl(true)
                .build();

        try {
            officeManager.start();

            // 第一步：先转换为 .docx 中间格式（比ODT格式更兼容）
            String intermediateFile = docFilePath.substring(0, docFilePath.lastIndexOf('.')) + "_temp.docx";

            // 加载属性 - 重点是接受修订
            Map<String, Object> loadProperties = new HashMap<>();
            loadProperties.put("UpdateDocMode", 1); // 接受所有修订
            loadProperties.put("ReadOnly", true);
            loadProperties.put("Hidden", true);
            loadProperties.put("LoadDocumentMode", 1); // 强制接受修订
            loadProperties.put("UpdateFields", true);
            loadProperties.put("UpdateLinks", true);

            // 针对.doc文件的特殊处理
//            loadProperties.put("GraphicResolution", 300);
            loadProperties.put("LoadGraphic", true);
            loadProperties.put("EmbedPictures", true);

            // 中间格式存储属性 - 使用.docx格式
            Map<String, Object> intermediateStoreProperties = new HashMap<>();
            intermediateStoreProperties.put("FilterName", "MS Word 2007 XML"); // DOCX格式
            intermediateStoreProperties.put("Overwrite", true);

            // 添加过滤器数据确保修订被接受
            Map<String, Object> intermediateFilterData = new HashMap<>();
            intermediateFilterData.put("ExportTrackedChanges", false);
            intermediateFilterData.put("UpdateDocMode", 1);
            intermediateStoreProperties.put("FilterData", intermediateFilterData);

            // 第一次转换：DOC -> DOCX
            DocumentConverter toDocxConverter = LocalConverter.builder()
                    .officeManager(officeManager)
                    .loadProperties(loadProperties)
                    .storeProperties(intermediateStoreProperties)
                    .build();

            System.out.println("第一步：DOC -> DOCX 转换中...");
            toDocxConverter.convert(new File(docFilePath))
                    .to(new File(intermediateFile))
                    .execute();

            // 等待文件写入完成
            Thread.sleep(2000);

            // 第二步：DOCX -> PDF，确保无修订痕迹
            Map<String, Object> pdfLoadProperties = new HashMap<>();
            pdfLoadProperties.put("UpdateDocMode", 1);
            pdfLoadProperties.put("ReadOnly", true);
            pdfLoadProperties.put("Hidden", true);

            Map<String, Object> pdfFilterData = new HashMap<>();
            // 核心属性：确保不导出或显示修订
            pdfFilterData.put("ExportTrackedChanges", false);
            pdfFilterData.put("ShowTrackedChanges", false);
            pdfFilterData.put("PrintChanges", false);
            pdfFilterData.put("PrintAnnotations", false);
            pdfFilterData.put("UseRedlineColors", false);
            pdfFilterData.put("ExportBookmarksToPDFDestination", false);//true
            pdfFilterData.put("ExportFormFields", false);//true
            pdfFilterData.put("EmbedStandardFonts", false);
            pdfFilterData.put("ExportBookmarks", false);//
            pdfFilterData.put("OpenBookmarkLevels", -1);
            pdfFilterData.put("ImagePDF", true); // 确保图片正确导出
            pdfFilterData.put("ImageResolution", 150); // 设置图像DPI
            pdfFilterData.put("PrintChanges", false);
            pdfFilterData.put("PrintAnnotations", false);
            pdfFilterData.put("UseRedlineColors", false);
            pdfFilterData.put("ExportNotes", false);
            pdfFilterData.put("ExportHiddenText", false);
            pdfFilterData.put("ExportPlaceholderFields", false);


            Map<String, Object> pdfStoreProperties = new HashMap<>();
            pdfStoreProperties.put("FilterData", pdfFilterData);
            pdfStoreProperties.put("FilterName", "writer_pdf_Export");
            pdfStoreProperties.put("Overwrite", true);

            // 第二次转换：DOCX -> PDF
            DocumentConverter toPdfConverter = LocalConverter.builder()
                    .officeManager(officeManager)
                    .loadProperties(pdfLoadProperties)
                    .storeProperties(pdfStoreProperties)
                    .build();

            System.out.println("第二步：DOCX -> PDF 转换中...");
            toPdfConverter.convert(new File(intermediateFile))
                    .to(new File(pdfFilePath))
                    .execute();

            // 删除中间文件
            try {
                File tempFile = new File(intermediateFile);
                if (tempFile.exists()) {
                    tempFile.delete();
                    System.out.println("临时文件已删除");
                }
            } catch (Exception e) {
                System.out.println("删除临时文件失败: " + e.getMessage());
            }

        } finally {
            officeManager.stop();
        }
    }

    public static void main(String[] args) {
        String docFilePath = "D:\\test\\gygy\\0723.doc";
        String pdfFilePath = "D:\\test\\gygy\\0723.pdf";
        String docFilePath1 = "D:\\test\\report\\report.docx";
        String pdfFilePath1 = "D:\\test\\report\\report.pdf";


//        docFilePath1 = "C:\\Users\\t1318\\Desktop\\税务\\供要管用\\222.doc";
//        pdfFilePath1 = "C:\\Users\\t1318\\Desktop\\税务\\供要管用\\222.pdf";
//        docFilePath1 = "D:\\test\\template-ryjl-1.docx";
//        pdfFilePath1 = "D:\\test\\template-ryjl-1.pdf";

//        docFilePath1 = "D:\\test\\template-1.docx";
//        pdfFilePath1 = "D:\\test\\template-1.pdf";

//        docFilePath1 = "D:\\test\\gygy\\系统设计说明书编写规范.doc";
//        pdfFilePath1 = "D:\\test\\gygy\\系统设计说明书编写规范.pdf";

//        docFilePath1 = "C:\\Users\\t1318\\Desktop\\税务\\供要管用\\0806.docx";
//        pdfFilePath1 = "C:\\Users\\t1318\\Desktop\\税务\\供要管用\\0806.pdf";

        docFilePath1 = "C:\\Users\\t1318\\Desktop\\税务\\供要管用\\gygy\\bgmb.docx";  // 输入文件路径
        pdfFilePath1 = "C:\\Users\\t1318\\Desktop\\税务\\供要管用\\gygy\\bgmb.pdf"; // 输出PDF路径

//        docFilePath1 = "C:\\Users\\t1318\\Desktop\\税务\\供要管用\\111.doc";
//        pdfFilePath1 = "C:\\Users\\t1318\\Desktop\\税务\\供要管用\\111.pdf";
//        docFilePath1 = "C:\\Users\\t1318\\Desktop\\税务\\供要管用\\222x.docx";
//        pdfFilePath1 = "C:\\Users\\t1318\\Desktop\\税务\\供要管用\\222x.pdf";

        try {
            long startTime = System.currentTimeMillis();

            // 根据文件扩展名选择转换方法
            if (docFilePath1.toLowerCase().endsWith(".doc")) {
                System.out.println("使用两步转换法处理 .doc 文件");
//                convertDocWithTwoStep(docFilePath1, pdfFilePath1);
//                convertDocWithTwoStep2(docFilePath1, pdfFilePath1);
//                convertDocCleanRevision(docFilePath1, pdfFilePath1);

                System.out.println("使用增强方法处理 .doc 文件");

                // 首先尝试命令行方式
                try {
                    System.out.println("尝试命令行转换...");
                    convertDocWithCommandLine(docFilePath1, pdfFilePath1);
//                    convertDocEnhanced(docFilePath1, pdfFilePath1);
//                    convertDocWithPreprocessing(docFilePath1, pdfFilePath1);
//                    convertDocWithUNO(docFilePath1, pdfFilePath1);
                } catch (Exception e) {
                    System.out.println("命令行转换失败: " + e.getMessage());
                    System.out.println("尝试 JODConverter 增强方式...");
//                    convertDocEnhanced(docFilePath1, pdfFilePath1);
                }
            } else {
                System.out.println("使用标准转换法处理 .docx 文件");
//                convertDoc2Pdf(docFilePath1, pdfFilePath1);
                convertDocWithCommandLine(docFilePath1, pdfFilePath1);
            }



//            convertDoc2Pdf(docFilePath1, pdfFilePath1);
//            convertDocInTwoSteps(docFilePath1, pdfFilePath1);
//            convertDocxToPdfPreserveFormat(docFilePath1, pdfFilePath1);
            long endTime = System.currentTimeMillis();

            System.out.println("转换完成！耗时: " + (endTime - startTime) + " ms");

            File pdfFile = new File(pdfFilePath1);
            if (pdfFile.exists()) {
                System.out.println("PDF文件大小: " + pdfFile.length() + " bytes");
                System.out.println("PDF文件 : " + pdfFilePath1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


    }


    public static void convertDocWithTwoStep(String docFilePath, String pdfFilePath) throws Exception {
        LocalOfficeManager officeManager = LocalOfficeManager.builder()
                .taskExecutionTimeout(180000L)
                .taskQueueTimeout(120000L)
                .disableOpengl(true)
                .build();

        try {
            officeManager.start();

            // 第一步：先转换为 .docx 或 .odt 中间格式
            String intermediateFile = docFilePath.substring(0, docFilePath.lastIndexOf('.')) + "_temp.odt";

            // 加载属性 - 重点是接受修订
            Map<String, Object> loadProperties = new HashMap<>();
            loadProperties.put("UpdateDocMode", 1); // 接受所有修订
            loadProperties.put("ReadOnly", true);
            loadProperties.put("Hidden", true);
            loadProperties.put("LoadDocumentMode", 1); // 强制接受修订

            // 中间格式存储属性
            Map<String, Object> intermediateStoreProperties = new HashMap<>();
            intermediateStoreProperties.put("FilterName", "writer8"); // ODT格式
            intermediateStoreProperties.put("Overwrite", true);

            // 第一次转换：DOC -> ODT
            DocumentConverter toOdtConverter = LocalConverter.builder()
                    .officeManager(officeManager)
                    .loadProperties(loadProperties)
                    .storeProperties(intermediateStoreProperties)
                    .build();

            toOdtConverter.convert(new File(docFilePath))
                    .to(new File(intermediateFile))
                    .execute();

            // 第二步：ODT -> PDF，确保无修订痕迹
            Map<String, Object> pdfFilterData = new HashMap<>();
            pdfFilterData.put("ExportTrackedChanges", false);
            pdfFilterData.put("ShowTrackedChanges", false);
            pdfFilterData.put("PrintChanges", false);
            pdfFilterData.put("PrintAnnotations", false);
            pdfFilterData.put("UseRedlineColors", false);
//            pdfFilterData.put("EmbedStandardFonts", true);
            pdfFilterData.put("ExportBookmarks", false);
            pdfFilterData.put("ImageResolution", 300);

            pdfFilterData.put("ExportBookmarksToPDFDestination", false);//true
            pdfFilterData.put("OpenBookmarkLevels", -1);

            pdfFilterData.put("PrintChanges", false);
            pdfFilterData.put("PrintAnnotations", false);
            pdfFilterData.put("UseRedlineColors", false);

            Map<String, Object> pdfStoreProperties = new HashMap<>();
            pdfStoreProperties.put("FilterData", pdfFilterData);
            pdfStoreProperties.put("FilterName", "writer_pdf_Export");
            pdfStoreProperties.put("Overwrite", true);

            // 第二次转换：ODT -> PDF
            DocumentConverter toPdfConverter = LocalConverter.builder()
                    .officeManager(officeManager)
                    .storeProperties(pdfStoreProperties)
                    .build();

            toPdfConverter.convert(new File(intermediateFile))
                    .to(new File(pdfFilePath))
                    .execute();

            // 删除中间文件
            try {
                File tempFile = new File(intermediateFile);
                if (tempFile.exists()) {
                    tempFile.delete();
                }
            } catch (Exception e) {
                System.out.println("删除临时文件失败: " + e.getMessage());
            }

        } finally {
            officeManager.stop();
        }
    }


    public static void convertDocEnhanced(String docFilePath, String pdfFilePath) throws Exception {
        // 首先尝试手动启动 LibreOffice 服务
        Process officeProcess = null;

        LocalOfficeManager officeManager = null;
        try {
            officeManager = LocalOfficeManager.builder()
                    .portNumbers(8100)
                    .taskExecutionTimeout(180000L)
                    .taskQueueTimeout(120000L)
                    .disableOpengl(true)
                    .build();

            officeManager.start();

            // 针对 .doc 文件的特殊加载属性
            Map<String, Object> loadProperties = new HashMap<>();
            loadProperties.put("UpdateDocMode", 1); // ACCEPT_ALL
            loadProperties.put("LoadDocumentMode", 1); // AUTOMATIC
            loadProperties.put("ReadOnly", true);
            loadProperties.put("Hidden", true);
            loadProperties.put("UpdateFields", true);
            loadProperties.put("UpdateLinks", true);
            loadProperties.put("GraphicResolution", 300);
            loadProperties.put("LoadGraphic", true);
            loadProperties.put("EmbedPictures", true);

            // 额外的 .doc 处理属性
            loadProperties.put("ShowChanges", false);
            loadProperties.put("ShowInlineChanges", false);
            loadProperties.put("ShowChangesInMargin", false);
            loadProperties.put("ShowAnnotations", false);

            // 详细的 PDF 导出属性
            Map<String, Object> filterData = new HashMap<>();
            // 修订相关
            filterData.put("ExportTrackedChanges", false);
            filterData.put("ShowTrackedChanges", false);
            filterData.put("PrintChanges", false);
            filterData.put("PrintAnnotations", false);
            filterData.put("UseRedlineColors", false);
            filterData.put("ExportNotes", false);
            filterData.put("ExportHiddenText", false);

            // 书签和表单
            filterData.put("ExportBookmarks", false);
            filterData.put("ExportBookmarksToPDFDestination", false);
            filterData.put("ExportFormFields", false);

            // 字体和图像
//            filterData.put("EmbedStandardFonts", true);
//            filterData.put("ImagePDF", true);
//            filterData.put("ImageResolution", 300);
//            filterData.put("ReduceImageResolution", false);

            // PDF 格式
            filterData.put("SelectPdfVersion", 1); // PDF/A-1a
            filterData.put("UseTaggedPDF", true);

            // 其他
            filterData.put("OpenBookmarkLevels", -1);
            filterData.put("ExportPlaceholderFields", false);
            filterData.put("ConvertOOoTargetToPDFTarget", false);

            Map<String, Object> storeProperties = new HashMap<>();
            storeProperties.put("FilterData", filterData);
            storeProperties.put("FilterName", "writer_pdf_Export");
            storeProperties.put("Overwrite", true);

            DocumentConverter converter = LocalConverter.builder()
                    .officeManager(officeManager)
                    .loadProperties(loadProperties)
                    .storeProperties(storeProperties)
                    .build();

            converter.convert(new File(docFilePath))
                    .to(new File(pdfFilePath))
                    .execute();

        } finally {
            if (officeManager != null) {
                officeManager.stop();
            }
            if (officeProcess != null) {
                officeProcess.destroy();
            }
        }
    }

    public static void convertDocWithCommandLine(String docFilePath, String pdfFilePath) throws Exception {
        // 检查文件是否存在
        File inputFile = new File(docFilePath);
        if (!inputFile.exists()) {
            throw new Exception("输入文件不存在: " + docFilePath);
        }

        // 构建 LibreOffice 命令行参数
        String libreOfficePath = findLibreOfficePath();
        if (libreOfficePath == null) {
            throw new Exception("未找到 LibreOffice 安装路径");
        }

        // 构建命令 - 添加接受修订的参数
        ProcessBuilder processBuilder = new ProcessBuilder();
        processBuilder.command(
                libreOfficePath,
                "--headless",
                "--invisible",
                "--nologo",
                "--nolockcheck",
//                "--accept-all-changes",  // 关键参数：接受所有修订
                "--convert-to", "pdf:writer_pdf_Export:{"
                        + "\"ExportTrackedChanges\":false,"
                        + "\"ShowTrackedChanges\":false,"
                        + "\"PrintChanges\":false,"
                        + "\"PrintAnnotations\":false,"
                        + "\"UseRedlineColors\":false,"
                        + "\"ExportBookmarks\":false,"
                        + "\"ExportFormFields\":false"
                        + "}",
                "--outdir", new File(pdfFilePath).getParent(),
                docFilePath
        );

        // 设置环境变量确保正确处理中文
        Map<String, String> environment = processBuilder.environment();
        environment.put("LANG", "zh_CN.UTF-8");

        System.out.println("执行命令: " + String.join(" ", processBuilder.command()));

        // 执行转换
        Process process = processBuilder.start();

        // 读取输出和错误流
        /*BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));

        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println("输出: " + line);
        }

        while ((line = errorReader.readLine()) != null) {
            System.err.println("错误: " + line);
        }*/

        int exitCode = process.waitFor();
        if (exitCode != 0) {
            throw new Exception("LibreOffice 命令执行失败，退出码: " + exitCode);
        }

        // 检查输出文件是否存在
        File outputFile = new File(pdfFilePath);
        if (!outputFile.exists()) {
            // LibreOffice 可能会生成不同名称的文件，需要重命名
            String defaultOutputName = docFilePath.replaceAll("\\.doc$", ".pdf");
            File defaultOutputFile = new File(defaultOutputName);
            if (defaultOutputFile.exists()) {
                if (defaultOutputFile.renameTo(outputFile)) {
                    System.out.println("文件已重命名为: " + pdfFilePath);
                } else {
                    throw new Exception("无法重命名输出文件");
                }
            } else {
                throw new Exception("PDF 文件未生成");
            }
        }

        System.out.println("命令行转换成功");
    }

    private static String findLibreOfficePath() {
        String osName = System.getProperty("os.name").toLowerCase();

        if (osName.contains("windows")) {
            // Windows 路径
            String[] possiblePaths = {
                    "C:\\Program Files\\LibreOffice\\program\\soffice.exe",
                    "C:\\Program Files (x86)\\LibreOffice\\program\\soffice.exe",
                    "C:\\Program Files\\LibreOffice 24\\program\\soffice.exe",
                    "C:\\Program Files (x86)\\LibreOffice 24\\program\\soffice.exe"
            };

            for (String path : possiblePaths) {
                File file = new File(path);
                if (file.exists()) {
                    return path;
                }
            }
        } else {
            // Linux/Mac 路径
            String[] possiblePaths = {
                    "/usr/bin/libreoffice",
                    "/usr/local/bin/libreoffice",
                    "/opt/libreoffice/program/soffice"
            };

            for (String path : possiblePaths) {
                File file = new File(path);
                if (file.exists()) {
                    return path;
                }
            }
        }

        return null;
    }

    public static void convertDocWithPreprocessing(String docFilePath, String pdfFilePath) throws Exception {
        // 步骤1: 先将 .doc 转换为干净的 .docx（接受所有修订）
        String cleanDocxPath = docFilePath.replaceAll("\\.doc$", "_clean.docx");

        // 使用命令行方式预处理
        String libreOfficePath = findLibreOfficePath();
        if (libreOfficePath == null) {
            throw new Exception("未找到 LibreOffice 安装路径");
        }

        // 构建预处理命令（接受所有修订并保存为 docx）
        ProcessBuilder processBuilder = new ProcessBuilder();
        processBuilder.command(
                libreOfficePath,
                "--headless",
                "--invisible",
                "--nologo",
                "--nolockcheck",
                "--convert-to", "docx",
                "--outdir", new File(cleanDocxPath).getParent(),
                docFilePath
        );

        System.out.println("执行预处理命令: " + String.join(" ", processBuilder.command()));

        Process process = processBuilder.start();
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));

        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println("预处理输出: " + line);
        }

        while ((line = errorReader.readLine()) != null) {
            System.err.println("预处理错误: " + line);
        }

        int exitCode = process.waitFor();
        if (exitCode != 0) {
            throw new Exception("LibreOffice 预处理失败，退出码: " + exitCode);
        }

        // 等待文件生成
        Thread.sleep(3000);

        // 检查预处理文件是否存在
        File cleanDocxFile = new File(cleanDocxPath);
        if (!cleanDocxFile.exists()) {
            // LibreOffice 可能生成了不同名称的文件
            String defaultName = docFilePath.replaceAll("\\.doc$", ".docx");
            File defaultFile = new File(defaultName);
            if (defaultFile.exists()) {
                if (defaultFile.renameTo(cleanDocxFile)) {
                    System.out.println("预处理文件重命名成功");
                }
            }
        }

        if (!cleanDocxFile.exists()) {
            throw new Exception("预处理文件未生成: " + cleanDocxPath);
        }

        // 步骤2: 将干净的 .docx 转换为 PDF
        try {
            LocalOfficeManager officeManager = LocalOfficeManager.builder()
                    .portNumbers(8100)
                    .taskExecutionTimeout(180000L)
                    .taskQueueTimeout(120000L)
                    .disableOpengl(true)
                    .build();

            try {
                officeManager.start();

                Map<String, Object> loadProperties = new HashMap<>();
                loadProperties.put("UpdateDocMode", 1);
                loadProperties.put("ReadOnly", true);
                loadProperties.put("Hidden", true);

                Map<String, Object> filterData = new HashMap<>();
                filterData.put("ExportTrackedChanges", false);
                filterData.put("ShowTrackedChanges", false);
                filterData.put("PrintChanges", false);
                filterData.put("PrintAnnotations", false);
                filterData.put("UseRedlineColors", false);
                filterData.put("ExportBookmarks", false);
                filterData.put("ExportBookmarksToPDFDestination", false);
                filterData.put("ExportFormFields", false);
//                filterData.put("EmbedStandardFonts", true);
//                filterData.put("ImagePDF", true);
//                filterData.put("ImageResolution", 300);
                filterData.put("SelectPdfVersion", 1);
                filterData.put("ExportNotes", false);
                filterData.put("ExportHiddenText", false);
                filterData.put("OpenBookmarkLevels", -1);

                Map<String, Object> storeProperties = new HashMap<>();
                storeProperties.put("FilterData", filterData);
                storeProperties.put("FilterName", "writer_pdf_Export");
                storeProperties.put("Overwrite", true);

                DocumentConverter converter = LocalConverter.builder()
                        .officeManager(officeManager)
                        .loadProperties(loadProperties)
                        .storeProperties(storeProperties)
                        .build();

                converter.convert(new File(cleanDocxPath))
                        .to(new File(pdfFilePath))
                        .execute();

                System.out.println("预处理+转换方式成功");

            } finally {
                officeManager.stop();
            }
        } finally {
            // 删除临时文件
            try {
                if (cleanDocxFile.exists()) {
                    cleanDocxFile.delete();
                    System.out.println("临时文件已删除: " + cleanDocxPath);
                }
            } catch (Exception e) {
                System.out.println("删除临时文件失败: " + e.getMessage());
            }
        }
    }

    public static void convertDocWithUNO(String inputDoc, String outputPdf) throws Exception {
        // 手动启动 LibreOffice 服务
        String libreOfficePath = findLibreOfficePath();
        if (libreOfficePath == null) {
            throw new Exception("未找到 LibreOffice 安装路径");
        }

        Process officeProcess = null;
        try {
            ProcessBuilder pb = new ProcessBuilder(
                    libreOfficePath,
                    "--headless",
                    "--accept=socket,host=127.0.0.1,port=8100;urp;"
            );
            officeProcess = pb.start();
            Thread.sleep(5000); // 等待服务启动
        } catch (Exception e) {
            System.out.println("启动 LibreOffice 服务失败: " + e.getMessage());
        }

        try {
            // 连接到 LibreOffice
            String connectionString = "uno:socket,host=127.0.0.1,port=8100;urp;StarOffice.ComponentContext";
//            com.sun.star.uno.XComponentContext xContext = com.sun.star.comp.helper.Bootstrap.bootstrap(connectionString);
            // 获取远程组件上下文
            XComponentContext xContext = Bootstrap.createInitialComponentContext(null);
            xContext = com.sun.star.comp.helper.Bootstrap.bootstrap(); // 若支持无参 bootstrap


            // 获取服务管理器
            com.sun.star.lang.XMultiComponentFactory xServiceManager = xContext.getServiceManager();
            // 创建 Uno URL 解析器
            XUnoUrlResolver urlResolver = UnoUrlResolver.create(xContext);

            // 使用 resolver 连接 LibreOffice 实例
            Object initialObject = urlResolver.resolve(connectionString);


            // 获取桌面服务
            Object desktop = xServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", xContext);
            com.sun.star.frame.XDesktop xDesktop = (com.sun.star.frame.XDesktop)
                    com.sun.star.uno.UnoRuntime.queryInterface(com.sun.star.frame.XDesktop.class, desktop);

            // 准备加载属性
            com.sun.star.beans.PropertyValue[] loadProps = new com.sun.star.beans.PropertyValue[5];
            loadProps[0] = new com.sun.star.beans.PropertyValue();
            loadProps[0].Name = "Hidden";
            loadProps[0].Value = true;

            loadProps[1] = new com.sun.star.beans.PropertyValue();
            loadProps[1].Name = "UpdateDocMode";
            loadProps[1].Value = 1; // ACCEPT_ALL

            loadProps[2] = new com.sun.star.beans.PropertyValue();
            loadProps[2].Name = "ReadOnly";
            loadProps[2].Value = true;

            loadProps[3] = new com.sun.star.beans.PropertyValue();
            loadProps[3].Name = "LoadDocumentMode";
            loadProps[3].Value = 1; // AUTOMATIC

            loadProps[4] = new com.sun.star.beans.PropertyValue();
            loadProps[4].Name = "ShowChanges";
            loadProps[4].Value = false;

            // 加载文档
            com.sun.star.frame.XComponentLoader loader = (com.sun.star.frame.XComponentLoader)
                    com.sun.star.uno.UnoRuntime.queryInterface(com.sun.star.frame.XComponentLoader.class, xDesktop);

            String fileUrl = toFileUrl(inputDoc);
            com.sun.star.lang.XComponent document = loader.loadComponentFromURL(fileUrl, "_blank", 0, loadProps);

            if (document == null) {
                throw new Exception("无法加载文档: " + inputDoc);
            }

            // 等待文档加载完成
            Thread.sleep(2000);

            // 获取文本文档接口
            com.sun.star.text.XTextDocument textDoc = (com.sun.star.text.XTextDocument)
                    com.sun.star.uno.UnoRuntime.queryInterface(com.sun.star.text.XTextDocument.class, document);

            if (textDoc != null) {
                // 尝试通过属性设置隐藏修订
                try {
                    com.sun.star.beans.XPropertySet propSet = (com.sun.star.beans.XPropertySet)
                            com.sun.star.uno.UnoRuntime.queryInterface(com.sun.star.beans.XPropertySet.class, textDoc);
                    if (propSet != null) {
                        propSet.setPropertyValue("ShowChanges", false);
                        propSet.setPropertyValue("ShowInlineChanges", false);
                        propSet.setPropertyValue("ShowChangesInMargin", false);
                    }
                } catch (Exception e) {
                    System.out.println("设置属性时出现异常: " + e.getMessage());
                }
            }

            // 准备导出属性
            com.sun.star.beans.PropertyValue[] storeProps = new com.sun.star.beans.PropertyValue[2];
            storeProps[0] = new com.sun.star.beans.PropertyValue();
            storeProps[0].Name = "FilterName";
            storeProps[0].Value = "writer_pdf_Export";

            storeProps[1] = new com.sun.star.beans.PropertyValue();
            storeProps[1].Name = "FilterData";
            com.sun.star.beans.PropertyValue[] filterData = new com.sun.star.beans.PropertyValue[15];

            filterData[0] = new com.sun.star.beans.PropertyValue();
            filterData[0].Name = "ExportTrackedChanges";
            filterData[0].Value = false;

            filterData[1] = new com.sun.star.beans.PropertyValue();
            filterData[1].Name = "ShowTrackedChanges";
            filterData[1].Value = false;

            filterData[2] = new com.sun.star.beans.PropertyValue();
            filterData[2].Name = "PrintChanges";
            filterData[2].Value = false;

            filterData[3] = new com.sun.star.beans.PropertyValue();
            filterData[3].Name = "PrintAnnotations";
            filterData[3].Value = false;

            filterData[4] = new com.sun.star.beans.PropertyValue();
            filterData[4].Name = "UseRedlineColors";
            filterData[4].Value = false;

            filterData[5] = new com.sun.star.beans.PropertyValue();
            filterData[5].Name = "ExportBookmarks";
            filterData[5].Value = false;

            filterData[6] = new com.sun.star.beans.PropertyValue();
            filterData[6].Name = "ExportBookmarksToPDFDestination";
            filterData[6].Value = false;

            filterData[7] = new com.sun.star.beans.PropertyValue();
            filterData[7].Name = "ExportFormFields";
            filterData[7].Value = false;

            filterData[8] = new com.sun.star.beans.PropertyValue();
            filterData[8].Name = "EmbedStandardFonts";
            filterData[8].Value = true;

            filterData[9] = new com.sun.star.beans.PropertyValue();
            filterData[9].Name = "ImagePDF";
            filterData[9].Value = true;

            filterData[10] = new com.sun.star.beans.PropertyValue();
            filterData[10].Name = "ImageResolution";
            filterData[10].Value = 300;

            filterData[11] = new com.sun.star.beans.PropertyValue();
            filterData[11].Name = "SelectPdfVersion";
            filterData[11].Value = 1;

            filterData[12] = new com.sun.star.beans.PropertyValue();
            filterData[12].Name = "ExportNotes";
            filterData[12].Value = false;

            filterData[13] = new com.sun.star.beans.PropertyValue();
            filterData[13].Name = "ExportHiddenText";
            filterData[13].Value = false;

            filterData[14] = new com.sun.star.beans.PropertyValue();
            filterData[14].Name = "OpenBookmarkLevels";
            filterData[14].Value = -1;

            storeProps[1].Value = filterData;

            // 导出为 PDF
            com.sun.star.frame.XStorable storable = (com.sun.star.frame.XStorable)
                    com.sun.star.uno.UnoRuntime.queryInterface(com.sun.star.frame.XStorable.class, document);

            if (storable != null) {
                String pdfUrl = toFileUrl(outputPdf);
                storable.storeToURL(pdfUrl, storeProps);
                System.out.println("UNO 方式转换成功");
            } else {
                throw new Exception("文档不支持存储操作");
            }

            // 关闭文档
            document.dispose();

        } finally {
            // 终止 LibreOffice 进程
            if (officeProcess != null) {
                officeProcess.destroy();
            }
        }
    }

    private static String toFileUrl(String path) {
        try {
            File file = new File(path);
            return file.toURI().toString();
        } catch (Exception e) {
            String normalizedPath = path.replace("\\", "/");
            if (!normalizedPath.startsWith("/")) {
                normalizedPath = "/" + normalizedPath;
            }
            return "file://" + normalizedPath;
        }
    }

}